package language.advanced.Concurrent;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.Data;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

//使用阻塞队列处理生产者消费者问题
public class BlockingQueueWriteExcelTest {
    private static final BlockingQueue<List<User>> bQueue = new LinkedBlockingQueue<>(3);

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;

    private static final int page = 40;

    public static void single(){
        ArrayList<User> users = new ArrayList<>();
        User user = new User();
        user.setUsername("a");
        user.setBirthday(new Date());
        users.add(user);

        while (true) {
            try {
                //不停地添加第四个，因为阻塞队列大小为3，所以无法添加并报异常
                bQueue.add(users);
                //这句话可能在第四个a之前或之后打印。因为消费者线程不是本线程
                System.out.println("成功添加第四个a，生产者等待消费者消费完");
                break;
            } catch (IllegalStateException e) {
                //阻塞队列已满,就会走到这里
            }
        }
    }

    @Test
    public void ddd(){
        ExcelWriter excel = EasyExcel.write("exportOutMultiBatch.xlsx", User.class).build();
        WriteSheet sheet = EasyExcel.writerSheet("sheetExample").build();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(QUEUE_CAPACITY), new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < page; i++) {
            executor.submit(BlockingQueueWriteExcelTest::single);
        }

        //启动单线程的消费者
        int count = 0;
        while (true) {
            try {
                List<User> info = bQueue.take();
                System.out.println(info);
                excel.write(info, sheet);
                count++;
                if (count >= page){
                    excel.finish();
                    return;
                }
            } catch (Exception e) {
                //take方法如果取不到元素，会阻塞以让出cpu占用权，所以这里走不到
                //take改成remove就能走到
                //take的异常为中断异常
                System.out.println("队列中已经没有元素了");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }

        }


    }
}



@Data
class User {

    @ExcelProperty("用户名")
    private String username;
    @ExcelProperty("生日")
    private Date birthday;
}

